package handler

import (
	"encoding/json"
	"log"
	"net/http"
	"sync"
	"time"

	"github.com/dahuamao/task-scheduler/config"
	"github.com/dahuamao/task-scheduler/model"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/gorilla/websocket"
)

// 客户端状态
type ClientStatus struct {
	Conn        *websocket.Conn
	IsBusy      bool        // 是否正在处理任务
	CurrentTask *model.Task // 当前处理的任务
	LastPing    time.Time   // 最后心跳时间
	Mutex       sync.Mutex  // 客户端级别的锁
}

// 客户端连接管理
var (
	clients     = make(map[string]*ClientStatus) // clientID -> 客户端状态
	clientMutex sync.RWMutex                     // 用于客户端操作的读写锁
)

// 注册客户端连接
func RegisterClient(clientID string, conn *websocket.Conn) {
	clientMutex.Lock()
	clients[clientID] = &ClientStatus{
		Conn:     conn,
		IsBusy:   false,
		LastPing: time.Now(),
	}
	clientMutex.Unlock()
	log.Printf("客户端 %s 已连接，当前连接数: %d", clientID, len(clients))
}

// 移除客户端连接
func RemoveClient(clientID string) {
	clientMutex.Lock()
	if client, exists := clients[clientID]; exists {
		// 如果客户端正在处理任务，将任务状态重置为待执行
		if client.IsBusy && client.CurrentTask != nil {
			config.DB.Model(&model.Task{}).
				Where("id = ?", client.CurrentTask.ID).
				Update("status", string(StatusPending))
			log.Printf("客户端 %s 断开连接，重置任务 %d 状态为待执行", clientID, client.CurrentTask.ID)
		}
		delete(clients, clientID)
	}
	clientMutex.Unlock()
	log.Printf("客户端 %s 已断开，当前连接数: %d", clientID, len(clients))
}

// 获取空闲客户端
func getAvailableClient() (string, *websocket.Conn) {
	clientMutex.RLock()
	defer clientMutex.RUnlock()

	for clientID, client := range clients {
		client.Mutex.Lock()
		if !client.IsBusy {
			client.IsBusy = true
			client.Mutex.Unlock()
			return clientID, client.Conn
		}
		client.Mutex.Unlock()
	}
	return "", nil
}

// 释放客户端
func releaseClient(clientID string) {
	clientMutex.RLock()
	client, exists := clients[clientID]
	clientMutex.RUnlock()

	if exists {
		client.Mutex.Lock()
		client.IsBusy = false
		client.CurrentTask = nil
		client.Mutex.Unlock()
	}
}

// 分发任务给客户端（改进的分配策略）
func DispatchTask(task model.Task) error {
	// 获取空闲客户端
	clientID, conn := getAvailableClient()
	if clientID == "" {
		log.Printf("没有可用的空闲客户端，任务 %d 等待分配", task.ID)
		return nil // 没有空闲客户端，等待下次调度
	}

	// 标记任务为处理中
	if err := config.DB.Model(&model.Task{}).
		Where("id = ?", task.ID).
		Update("status", string(StatusRunning)).Error; err != nil {
		// 如果更新失败，释放客户端
		releaseClient(clientID)
		return err
	}

	// 更新客户端状态
	clientMutex.RLock()
	client := clients[clientID]
	clientMutex.RUnlock()

	client.Mutex.Lock()
	client.CurrentTask = &task
	client.Mutex.Unlock()

	// 发送任务给客户端
	msg := map[string]interface{}{
		"type": "task",
		"task": task,
	}

	data, _ := json.Marshal(msg)
	if err := conn.WriteMessage(websocket.TextMessage, data); err != nil {
		// 发送失败，重置任务状态并释放客户端
		config.DB.Model(&model.Task{}).
			Where("id = ?", task.ID).
			Update("status", string(StatusPending))
		releaseClient(clientID)
		return err
	}

	log.Printf("任务 %d 已分发给空闲客户端 %s", task.ID, clientID)
	return nil
}

// 获取客户端统计信息
func GetClientStats() map[string]interface{} {
	clientMutex.RLock()
	defer clientMutex.RUnlock()

	total := len(clients)
	busy := 0
	idle := 0

	for _, client := range clients {
		client.Mutex.Lock()
		if client.IsBusy {
			busy++
		} else {
			idle++
		}
		client.Mutex.Unlock()
	}

	return map[string]interface{}{
		"total_clients": total,
		"busy_clients":  busy,
		"idle_clients":  idle,
	}
}

// 客户端健康检查
func StartClientHealthCheck() {
	ticker := time.NewTicker(30 * time.Second) // 每30秒检查一次
	defer ticker.Stop()

	log.Println("客户端健康检查启动...")

	for range ticker.C {
		clientMutex.Lock()
		now := time.Now()
		var disconnectedClients []string

		for clientID, client := range clients {
			client.Mutex.Lock()
			// 检查心跳超时（超过60秒没有心跳）
			if now.Sub(client.LastPing) > 60*time.Second {
				log.Printf("客户端 %s 心跳超时，准备断开连接", clientID)
				disconnectedClients = append(disconnectedClients, clientID)
			}
			client.Mutex.Unlock()
		}

		// 断开超时的客户端
		for _, clientID := range disconnectedClients {
			if client, exists := clients[clientID]; exists {
				// 如果客户端正在处理任务，重置任务状态
				if client.IsBusy && client.CurrentTask != nil {
					config.DB.Model(&model.Task{}).
						Where("id = ?", client.CurrentTask.ID).
						Update("status", string(StatusPending))
					log.Printf("客户端 %s 心跳超时，重置任务 %d 状态为待执行", clientID, client.CurrentTask.ID)
				}
				client.Conn.Close()
				delete(clients, clientID)
			}
		}
		clientMutex.Unlock()

		if len(disconnectedClients) > 0 {
			log.Printf("断开 %d 个超时客户端，当前连接数: %d", len(disconnectedClients), len(clients))
		}
	}
}

func HandleWebSocket(c *gin.Context) {
	upgrader := websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Printf("WebSocket升级失败: %v", err)
		return
	}
	defer conn.Close()

	// 生成客户端ID
	clientID := uuid.New().String()
	RegisterClient(clientID, conn)
	defer RemoveClient(clientID)

	// 处理客户端消息
	for {
		_, msg, err := conn.ReadMessage()
		if err != nil {
			log.Printf("客户端 %s 消息读取失败: %v", clientID, err)
			break
		}

		// 解析客户端消息
		var data map[string]interface{}
		if err := json.Unmarshal(msg, &data); err != nil {
			log.Printf("消息解析失败: %v", err)
			continue
		}

		// 处理心跳消息
		if data["type"] == "ping" {
			clientMutex.RLock()
			if client, exists := clients[clientID]; exists {
				client.Mutex.Lock()
				client.LastPing = time.Now()
				client.Mutex.Unlock()
			}
			clientMutex.RUnlock()

			// 回复心跳
			response := map[string]interface{}{"type": "pong"}
			responseData, _ := json.Marshal(response)
			conn.WriteMessage(websocket.TextMessage, responseData)
			continue
		}

		// 处理任务结果
		if data["type"] == "result" {
			taskID := data["task_id"].(float64)
			resultStr := data["result"].(string)
			success := data["success"].(bool)

			// 验证result是否为合法JSON
			if !json.Valid([]byte(resultStr)) {
				log.Printf("result不是合法JSON: %s", resultStr)
				continue
			}

			if err := HandleTaskResult(int(taskID), resultStr, success); err != nil {
				log.Printf("更新任务结果失败: %v", err)
			}

			// 释放客户端
			releaseClient(clientID)
			log.Printf("客户端 %s 完成任务 %d，已释放", clientID, int(taskID))
		}
	}
}

// GetClientStatusAPI 获取客户端状态的HTTP API（支持分页）
func GetClientStatusAPI(c *gin.Context) {
	// 获取分页参数
	params := GetPaginationParams(c)

	stats := GetClientStats()

	// 获取详细的客户端信息
	clientMutex.RLock()
	allClientDetails := make([]map[string]interface{}, 0)
	for clientID, client := range clients {
		client.Mutex.Lock()
		detail := map[string]interface{}{
			"client_id":    clientID,
			"is_busy":      client.IsBusy,
			"last_ping":    client.LastPing.Format(time.RFC3339),
			"current_task": nil,
		}
		if client.CurrentTask != nil {
			detail["current_task"] = map[string]interface{}{
				"id":    client.CurrentTask.ID,
				"title": client.CurrentTask.Title,
			}
		}
		client.Mutex.Unlock()
		allClientDetails = append(allClientDetails, detail)
	}
	clientMutex.RUnlock()

	// 使用分页工具包处理切片分页
	response := PaginateSlice(allClientDetails, params)

	// 包装响应数据
	response.Data = gin.H{
		"stats":          stats,
		"client_details": response.Data,
	}

	c.JSON(200, response)
}
